#include "aht20.h"

mI2CTypedef_t CJLI2c;			//io模拟i2c接口
#define CJL_ADDR 	(0x38<<1)

static void i2c_SdaH(void){
	HAL_GPIO_SetInOut(GPIOD, GPIO_PIN_6, ENABLE, DISABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_RESET);
}

static void i2c_SdaL(void){
	HAL_GPIO_SetInOut(GPIOD, GPIO_PIN_6, ENABLE, ENABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_RESET);
}

static void i2c_SclH(void){
	HAL_GPIO_SetInOut(GPIOD,GPIO_PIN_7, ENABLE, DISABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);
}

static void i2c_SclL(void){
	HAL_GPIO_SetInOut(GPIOD, GPIO_PIN_7, ENABLE, ENABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);
}

static u8 i2c_ReadSda(void){
	return HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_6);
}

static u8 i2c_ReadScl(void){
	return HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_7);
}


void cjl_i2c_init(mI2CTypedef_t *i2c){
	GPIO_InitTypeDef GPIO_Initure;

	GPIO_Initure.Pin = GPIO_PIN_6| GPIO_PIN_7;
	GPIO_Initure.OutputEn = DISABLE;
	GPIO_Initure.InputEn = ENABLE;
	GPIO_Initure.PullupEn = ENABLE;
	HAL_GPIO_Init(GPIOD, &GPIO_Initure);

	i2c->IIC_InitPort=0;
	i2c->IIC_SDA_H=i2c_SdaH;
	i2c->IIC_SDA_L=i2c_SdaL;
	i2c->IIC_SCL_H=i2c_SclH;
	i2c->IIC_SCL_L=i2c_SclL;
	i2c->IIC_READ_SDA=i2c_ReadSda;
	i2c->IIC_READ_SCL=i2c_ReadScl;
}

//从uWriteAddress地址开始写入len字节数据					//通常情况下可以这样读写，但是顶不住有些设备与众不同，所以具体读写时序还要看芯片手册
void cjl_i2c_write(u8 uWriteAddress,u8 *buf,u8 len)
{
	i2c_Start(&CJLI2c);
	i2c_SendByte(&CJLI2c,CJL_ADDR|I2C_WR);
	i2c_WaitAck(&CJLI2c);
	i2c_SendByte(&CJLI2c,(uWriteAddress) & 0xFF);
	i2c_WaitAck(&CJLI2c);
	while(len--){
		i2c_SendByte(&CJLI2c,*buf++);
		i2c_WaitAck(&CJLI2c);
	}
	i2c_Stop(&CJLI2c);
}
//从uWriteAddress地址开始读出len字节数据
u8 cjl_i2c_read(u8 *buf,u8 len)
{
	i2c_Start(&CJLI2c);
	i2c_SendByte(&CJLI2c,CJL_ADDR|I2C_RD);
	if(1==i2c_WaitAck(&CJLI2c)){	//ERROR
		goto ERR;
	}
	while(len-->1){
		*buf++ = i2c_ReadByte(&CJLI2c);
		i2c_Ack(&CJLI2c);
	}
	*buf++ = i2c_ReadByte(&CJLI2c);
	i2c_NAck(&CJLI2c);
	i2c_Stop(&CJLI2c);
	return 1;//正常返回
ERR:
	i2c_SdaErrorClear(&CJLI2c);
	return 0;	
}

//CRC校验类型：CRC8/MAXIM
//多项式：X8+X5+X4+1
//Poly：0011 0001  0x31
//高位放到后面就变成 1000 1100 0x8c
//C现实代码：
uint8_t Calc_CRC8(uint8_t *message,uint8_t Num)
{
	uint8_t i;
	uint8_t byte;
	uint8_t crc=0xFF;
	for(byte=0; byte<Num; byte++)
	{
		crc^=(message[byte]);
		for(i=8; i>0; --i)
		{
			if(crc&0x80) crc=(crc<<1)^0x31;
			else crc=(crc<<1);
		}
	}
	return crc;
}

u8 AHT20_Read_Status(void)//读取状态寄存器
{
	uint8_t Byte_first;
	cjl_i2c_read(&Byte_first,1);
	return Byte_first;
}
uint8_t AHT20_Read_Cal_Enable(void)  //查询cal enable位有没有使能
{
	uint8_t val = 0;//ret = 0,
	val = AHT20_Read_Status();
	if((val & 0x68)==0x08)
		return 1;
	else  return 0;
}
void AHT20_SendAC(void) //向AHT20发送AC命令
{
	u8 buf[2]={0x33,0x00};
	cjl_i2c_write(0xac,buf,2);
}
void AHT20_Read_CTdata_crc(uint32_t *ct) //CRC校验后，读取AHT20的温度和湿度数据
{
	uint32_t RetuData = 0;
	uint16_t cnt = 0;
	// uint8_t  CRCDATA=0;
	uint8_t  CTDATA[7]= {0}; //用于CRC传递数组

	AHT20_SendAC();//向AHT10发送AC命令
	HAL_Delay(80);//延时80ms左右
	cnt = 0;
	while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0，表示为空闲状态，若为1，表示忙状态
	{
		delay_us(1508);
		if(cnt++>=100)
		{
			break;
		}
	}

	cjl_i2c_read(CTDATA,7);
	

	if(Calc_CRC8(CTDATA,6)==CTDATA[6])
	{
		RetuData = (RetuData|CTDATA[1])<<8;
		RetuData = (RetuData|CTDATA[2])<<8;
		RetuData = (RetuData|CTDATA[3]);
		RetuData =RetuData >>4;
		ct[0] = RetuData;//湿度
		RetuData = 0;
		RetuData = (RetuData|CTDATA[3])<<8;
		RetuData = (RetuData|CTDATA[4])<<8;
		RetuData = (RetuData|CTDATA[5]);
		RetuData = RetuData&0xfffff;
		ct[1] =RetuData; //温度
	}
	else
	{
		ct[0]=0x00;
		ct[1]=0x00;//校验错误返回值，客户可以根据自己需要更改
	}//CRC数据
}

void JH_Reset_REG(uint8_t addr)
{

	uint8_t Byte_first,Byte_second,Byte_third;
	i2c_Start(&CJLI2c);
	i2c_SendByte(&CJLI2c,0x70);
	i2c_WaitAck(&CJLI2c);
	i2c_SendByte(&CJLI2c,addr);
	i2c_WaitAck(&CJLI2c);
	i2c_SendByte(&CJLI2c,0x00);
	i2c_WaitAck(&CJLI2c);
	i2c_SendByte(&CJLI2c,0x00);
	i2c_WaitAck(&CJLI2c);
	i2c_Stop(&CJLI2c);

	HAL_Delay(5);//延时5ms左右
	i2c_Start(&CJLI2c);
	i2c_SendByte(&CJLI2c,0x71);
	i2c_WaitAck(&CJLI2c);
	Byte_first = i2c_ReadByte(&CJLI2c);
	i2c_Ack(&CJLI2c);
	Byte_second = i2c_ReadByte(&CJLI2c);
	i2c_Ack(&CJLI2c);
	Byte_third = i2c_ReadByte(&CJLI2c);
	i2c_NAck(&CJLI2c);   
	i2c_Stop(&CJLI2c);

	HAL_Delay(10);//延时10ms左右
	i2c_Start(&CJLI2c);
	i2c_SendByte(&CJLI2c,0x70);
	i2c_WaitAck(&CJLI2c);
	i2c_SendByte(&CJLI2c,0xB0|addr);
	i2c_WaitAck(&CJLI2c);
	i2c_SendByte(&CJLI2c,Byte_second);
	i2c_WaitAck(&CJLI2c);
	i2c_SendByte(&CJLI2c,Byte_third);
	i2c_WaitAck(&CJLI2c);
	i2c_Stop(&CJLI2c);

	Byte_second=0x00;
	Byte_third =0x00;
}

void AHT20_Start_Init(void)
{
	JH_Reset_REG(0x1b);
	JH_Reset_REG(0x1c);
	JH_Reset_REG(0x1e);
}



void aht_init(void)
{
	cjl_i2c_init(&CJLI2c);
	HAL_Delay(100);	//等待芯片就绪
	if((AHT20_Read_Status()&0x18)!=0x18)
	{
		AHT20_Start_Init(); //重新初始化寄存器
		HAL_Delay(10);
	}
	
}

void aht_read_data(u8 *buf)  
{
	uint32_t CT_data[2];
	u16 humi,temp;
	AHT20_Read_CTdata_crc(CT_data);  //crc校验后，读取AHT20的温度和湿度数据
	humi =CT_data[0]*100*10/1024/1024;  //计算得到湿度值c1（放大了10倍）
	temp =CT_data[1]*200*10/1024/1024-500;//计算得到温度值t1（放大了10倍）
	printf("温度=%d,湿度=%d\r\n",CT_data[1],CT_data[0]);
	printf("温度=%d,湿度=%d",temp,humi);
	buf[0]=temp>>8;	//温度高
	buf[1]=temp;	//温度低
	buf[2]=humi>>8;	//湿度高
	buf[3]=humi;	//湿度低
	
}

